package com.beerandjesus.sportofkings.handicapper.profile.resolver;

import com.beerandjesus.sportofkings.handicapper.profile.AnalysisProfile;
import com.beerandjesus.sportofkings.handicapper.profile.AnalysisProfileBuilder;
import com.beerandjesus.sportofkings.handicapper.model.*;
import com.beerandjesus.sportofkings.handicapper.model.brisnet.singlefile.HorseRace;
import com.beerandjesus.sportofkings.handicapper.model.brisnet.singlefile.Horse;
import com.beerandjesus.sportofkings.handicapper.model.brisnet.singlefile.Race;
import com.beerandjesus.sportofkings.handicapper.model.brisnet.singlefile.PastPerformance;
import com.beerandjesus.sportofkings.handicapper.dao.Database;

import java.util.List;

import static com.beerandjesus.sportofkings.handicapper.profile.AnalysisProfile.Type.*;

/**
 * This profile is characterized by a drop in class from the previous race coupled
 * with a switch to a better jockey or another jockey of the same quality, as
 * described by Marc Cramer.
 * Date: Jul 6, 2012
 * Time: 3:46:46 PM
 */
public class CramerAnalysisProfileResolver implements AnalysisProfileResolver {

    private Database database;

    public AnalysisProfile resolve(HorseRace race, Horse horse) {
        // === Must be a Cramer-defined drop in class
        Race r = race.getRace();
        RaceType type = r.getType();
        if (type == null) {
            return null;
        }
        List<PastPerformance> pps = horse.getPastPerformances();
        if (pps == null || pps.size() == 0) {
            return null;
        }
        PastPerformance lastRacePerformance = pps.get(0);
        if (lastRacePerformance == null) {
            return null;
        }
        RaceType lastType = lastRacePerformance.getRaceType();
        if (lastType == null) {
            return null;
        }
        Integer claimingPrice = null;
        Integer lastClaimingPrice = null;
        if (!type.isCramerClassDrop(claimingPrice, lastType, lastClaimingPrice)) {
            return null;
        }
        // === We have a class drop
        AnalysisProfile prof = AnalysisProfileBuilder.analysisProfile(CRAMER_DROP_IN_CLASS_POSS_JOCKEY_SWITCH, 0);
        // === Must also be a jockey switch, either to a higher class jockey or
        // another jockey of the same class
        TrainerJockeyOwner tjo = horse.getTrainerJockeyOwner();
        if (tjo == null) {
            return prof;
        }
        String jock = tjo.getJockeyName();
        String lastJock = lastRacePerformance.getJockeyName();
        if (jock == null || lastJock == null) {
            return prof;
        }
        if (jock.equals(lastJock)) {
            // Can be the same jockey if the jockey won the last race
            String finPos = lastRacePerformance.getFinishPosition();
            int pos = 0;
            try {
                pos = Integer.valueOf(finPos);
            } catch (NumberFormatException e) {
                // Ignore
            }
            if (pos == 1) {
                // === Profile applies becasue the jockey won the last race
                CramerClassDropJockeySwitchProfile p = AnalysisProfileBuilder.cramerClassDropJockeySwitchProfile();
                p.setRiderWonBeforeWithHorse(true);
                return p;
            }
            return null;
        }
        // === We have a jockey switch.
        JockeyRating rating = getDatabase().getJockeyRatingByName(jock);
        JockeyRating lastRating = getDatabase().getJockeyRatingByName(lastJock);
        if (rating == null || lastRating == null) {
            return prof;
        }
        CramerJockeyRating currentJockeyRating = rating.getRating();
        CramerJockeyRating lastJockeyRating = lastRating.getRating();
        // Can be switch within same class, as long as the class is not unfavorable (UNKNOWN or OTHER)
        if (isSwitchWithinUnfavorableClass(currentJockeyRating, lastJockeyRating)) {
            // === Switch is withing unfavorable class. Profile does not apply.
            return null;
        }
        if (currentJockeyRating.ordinal() >= lastJockeyRating.ordinal()) {
            // === We have a switch within a favorable class or to a better class
            CramerClassDropJockeySwitchProfile cramerProfile = AnalysisProfileBuilder.cramerClassDropJockeySwitchProfile();
            if (currentJockeyRating.equals(CramerJockeyRating.LEADING)) {
                cramerProfile.setLeadingJockey(true);
            }
            if (RaceType.isDropFromAllowanceTo40KClaiming(lastType, type, race.getRace().getPurse())) {
                cramerProfile.setDropFromAllowanceTo40KClaiming(true);
            }
            boolean isWinningJockey = false;
            // Check to see if this jockey won a previous race on this horse
            for (PastPerformance past : pps) {
                if (past.getJockeyName() != null && past.getJockeyName().equals(jock)
                        && past.getFinishPosition() != null && past.getFinishPosition().equals("1")) {
                    isWinningJockey = true;
                    break;
                }
            }
            cramerProfile.setRiderWonBeforeWithHorse(isWinningJockey);
            return cramerProfile;
        }
        return null;
    }

    private boolean isSwitchWithinUnfavorableClass(CramerJockeyRating currentJockeyRating, CramerJockeyRating lastJockeyRating) {
        return (currentJockeyRating.equals(CramerJockeyRating.OTHER) &&
                lastJockeyRating.equals(CramerJockeyRating.OTHER)) ||
                (currentJockeyRating.equals(CramerJockeyRating.UNKNOWN) &&
                lastJockeyRating.equals(CramerJockeyRating.UNKNOWN));
    }

    public Database getDatabase() {
        return database;
    }

    public void setDatabase(Database database) {
        this.database = database;
    }
}
